home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / zc / g2.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  12KB  |  627 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    g2.c
  12.  *
  13.  *    Generate code for binary nodes.
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include "param.h"
  18. #include "nodes.h"
  19. #include "flags.h"
  20. #include "bstok.h"
  21. #include "gen.h"
  22. #include "ops.h"
  23.  
  24. #define FAIL    0
  25. #define OKAY    1
  26.  
  27. extern int cookflags[];
  28.  
  29. #define isimmed(np)     ((np)->g_flags & IMMEDID)
  30. #define isareg(np)      ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  31.  
  32. struct bop {
  33.     char *s_op, *u_op;
  34.     int opflags;
  35. } bops[] = {
  36.     {"muls",        "mulu", EOPD |ASSOC},
  37.     {"divs",        "divu", EOPD},
  38.     {"divs",        "divu", EOPD},
  39.     {"and",         "and",  EOPD|DOPE|IOPE |ASSOC},
  40.     {"or",          "or",   EOPD|DOPE|IOPE |ASSOC},
  41.     {"eor",         "eor",  DOPE|IOPE |ASSOC},
  42.     {"add",         "add",  EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC},
  43.     {"sub",         "sub",  EOPD|DOPE|EOPA|IOPE|AOPA|AOPD},
  44.     {"asl",         "lsl",  DOPD|QOPD|ONEOPM},
  45.     {"asr",         "lsr",  DOPD|QOPD|ONEOPM},
  46. };
  47.  
  48. char *tstnm[] = {
  49.     "lt",           /* < */
  50.     "gt",           /* > */
  51.     "le",           /* <= */
  52.     "ge",           /* >= */
  53.     "eq",           /* == */
  54.     "ne",           /* != */
  55. };
  56.  
  57. int tstx[] = {
  58.     B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE
  59. };
  60.  
  61. char *utstnm[] = {
  62.     "cs",           /* < */
  63.     "hi",           /* > */
  64.     "ls",           /* <= */
  65.     "cc",           /* >= */
  66.     "eq",           /* == */
  67.     "ne",           /* != */
  68. };
  69.  
  70. int utstx[] = {
  71.     B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE
  72. };
  73.  
  74. b_eval(np, cookie)
  75. register NODEP np;
  76. {
  77.     NODEP lp = np->n_left, rp = np->n_right;
  78.     NODEP tp;
  79.     int lcook = FORADR, rcook = FORADR;
  80.  
  81.     switch (np->g_token) {          /* special cookies */
  82.     case DOUBLE '&':
  83.     case DOUBLE '|':
  84.         lcook = rcook = FORCC;
  85.         break;
  86.     case '?':
  87.         lcook = FORCC;
  88.         break;
  89.     case '(':
  90.         rcook = FORPUSH;
  91.         break;
  92.     case ',':
  93.         if (np->g_offs) /* function args */
  94.             lcook = rcook = FORPUSH;
  95.         else {
  96.             lcook = FORSIDE;
  97.             rcook = cookie;
  98.         }
  99.         break;
  100.     case '=':
  101.         rcook = FORIMA;
  102.         break;
  103.     case '+':
  104.     case '-':
  105.         tp = rp;
  106.         while (tp->g_token == TCONV && tp->g_ty != ET_F)
  107.             tp = tp->n_left;
  108.         if (tp->g_token == ICON)
  109.             lcook = FORIMA;
  110.         break;
  111.     }
  112.  
  113.     if (np->g_type == EV_LR) {
  114.         if (eval(lp,lcook) == FAIL)
  115.             return FAIL;
  116.         freetmps(lp);
  117.         if (eval(rp,rcook) == FAIL)
  118.             return FAIL;
  119.         freetmps(rp);
  120.     } else if (np->g_type == EV_RL) {
  121.         if (eval(rp,rcook) == FAIL)
  122.             return FAIL;
  123.         freetmps(rp);
  124.         if (eval(lp,lcook) == FAIL)
  125.             return FAIL;
  126.         freetmps(lp);
  127.     } else {    /* EV_LRSEP */
  128.         if (eval(lp,lcook) == FAIL)
  129.             return FAIL;
  130.         freetmps(lp);
  131.         free1(NULL, lp);
  132.         if (eval(rp,rcook) == FAIL)
  133.             return FAIL;
  134.         freetmps(rp);
  135.     }
  136.     return b_sube(np, cookflags[cookie]);
  137. }
  138.  
  139. b_sube(np, flags)
  140. register NODEP np;
  141. {
  142.     NODEP lp = np->n_left, rp = np->n_right;
  143.     register int i, r;
  144.     int argsize;
  145.     char buf[40];
  146.  
  147.     if (isassign(np->g_token))
  148.         return as_eval(np);
  149.  
  150.     switch (np->g_token) {
  151.     case '=':
  152.         if (specasn(np, flags) || strasn(np))
  153.             return OKAY;
  154.         inherit(np);
  155.         addcode(np, "\tmove.S\t>A,<A\n");
  156.         return OKAY;
  157.  
  158.     case '(':
  159.         argsize = argmod(rp);
  160.         free1(NULL,rp);
  161.         if (np->g_ty == ET_A) {         /* struct returned */
  162.             frc_ral(AREG);
  163.             indir(np, AREG);
  164.         } else {
  165.             frc_ral(0);
  166.             retreg(np, 0);
  167.         }
  168.          externfuncref(np);
  169.         sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize);
  170.         addcode(np, buf);
  171.         return OKAY;
  172.  
  173.     case ',':
  174.         if (np->g_offs == 0)    /* normal ',' */
  175.             rinherit(np);
  176.         return OKAY;
  177.  
  178.     case DOUBLE '&':
  179.         free1(NULL, rp);
  180.         r = ralloc(0);
  181.         retreg(np, r);
  182.         holdlbls(np);
  183.         np->g_betw = iscc(lp) ? "<FL1\n" :
  184.             "<Q\tbeq\tL1\n";
  185.         addcode(np, iscc(rp) ? ">FL1\n" :
  186.             ">Q\tbeq\tL1\n");
  187.         addcode(np, "\tmoveq\t#1,A\n");
  188.         addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n");
  189.         return OKAY;
  190.  
  191.     case DOUBLE '|':
  192.         free1(NULL, rp);
  193.         r = ralloc(0);
  194.         retreg(np, r);
  195.         holdlbls(np);
  196.         np->g_betw = iscc(lp) ? "<TL1\n" :
  197.             "<Q\tbne\tL1\n";
  198.         addcode(np, iscc(rp) ? ">TL1\n" :
  199.             ">Q\tbne\tL1\n");
  200.         addcode(np, "\tclr\tA\n");
  201.         addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n");
  202.         return OKAY;
  203.  
  204.     case '?':
  205.         rinherit(np);
  206.         rinhlbls(np);
  207.         np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n";
  208.         return OKAY;
  209.  
  210.     case ':':
  211.         free1(NULL, rp);
  212.         r = ralloc(0);
  213.         retreg(np, r);
  214.         holdlbls(np);
  215.         np->g_betw = same_a(np, lp) ?
  216.             "\tbra\tL2\nL1:\n"  :
  217.             "\tmove.S\t<A,A\n\tbra\tL2\nL1:\n";
  218.         if (!same_a(np, rp))
  219.             addcode(np, "\tmove.S\t>A,A\n");
  220.         addcode(np, "L2:\n");
  221.         return OKAY;
  222.  
  223.     case '<':
  224.         i = 0;    goto dotst;
  225.     case '>':
  226.         i = 1;    goto dotst;
  227.     case LTEQ:
  228.         i = 2;    goto dotst;
  229.     case GTEQ:
  230.         i = 3;    goto dotst;
  231.     case DOUBLE '=':
  232.         i = 4;    goto dotst;
  233.     case NOTEQ:
  234.         i = 5;
  235. dotst:
  236.         fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD);
  237.         if (flags & CC_OK) {
  238.             np->g_token = (lp->g_ty == ET_U ?
  239.             utstx[i] : tstx[i]) + BR_TOK;
  240.         } else {
  241.             strcpy(np->n_name, lp->g_ty == ET_U ?
  242.             utstnm[i] : tstnm[i]);
  243.             r = ralloc(0);
  244.             retreg(np, r);
  245.             addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  246.         }
  247.         return OKAY;
  248.  
  249.     case '*':
  250.         return fixmul(np, bops[0].opflags);
  251.     case '/':
  252.         return fixdiv(np, bops[1].opflags);
  253.     case '%':
  254.         return fixmod(np, bops[2].opflags);
  255.     case '&':       i = 3;  goto doop;
  256.     case '|':       i = 4;  goto doop;
  257.     case '^':       i = 5;  goto doop;
  258.     case '+':
  259.         if (optadd(np, flags, 1))
  260.             return OKAY;
  261.             i = 6;    goto doop;
  262.     case '-':
  263.         if (optadd(np, flags, -1))
  264.             return OKAY;
  265.             i = 7;    goto doop;
  266.     case DOUBLE '<':i = 8;  goto doop;
  267.     case DOUBLE '>':i = 9;
  268. doop:
  269.         strcpy(np->n_name, np->g_ty == ET_U ?
  270.             bops[i].u_op : bops[i].s_op);
  271.         r = fix2ops(np, bops[i].opflags);
  272.         cc_hack(np);
  273.         return r;
  274.     case FIELDAS:
  275.         return fldasn(np, flags);
  276.     default:
  277.         printf("Weird b_eval %s ", np->n_name);
  278.         return FAIL;
  279.     }
  280. }
  281.  
  282. as_eval(np)
  283. register NODEP np;
  284. {
  285.     NODEP rp = np->n_right;
  286.     register int op, i, r;
  287.  
  288.     rp = np->n_right;
  289.  
  290.     op = np->g_token;
  291.     op -= ASSIGN 0;
  292.     switch (op) {
  293.  
  294.     /* these get unfolded now */
  295.     case '*':
  296.             return fixamul(np, bops[0].opflags);
  297.     case '/':
  298.             return fixadiv(np, bops[1].opflags);
  299.     case '%':
  300.             return fixamod(np, bops[2].opflags);
  301.     case '&':       i = 3;  goto doop;
  302.     case '|':       i = 4;  goto doop;
  303.     case '^':       i = 5;  goto doop;
  304.     case '+':       i = 6;  goto doop;
  305.     case '-':       i = 7;  goto doop;
  306.     case DOUBLE '<':i = 8;  goto doop;
  307.     case DOUBLE '>':i = 9;
  308. doop:
  309.         strcpy(np->n_name, np->g_ty == ET_U ?
  310.             bops[i].u_op : bops[i].s_op);
  311.         r = fix_asn(np, bops[i].opflags);
  312.         cc_hack(np);
  313.         return r;
  314.  
  315.     default:
  316.         printf("Weird as_eval %s ", np->n_name);
  317.         return FAIL;
  318.     }
  319. }
  320.  
  321. rinherit(np)
  322. register NODEP np;
  323. {
  324.     register NODEP rp = np->n_right;
  325.  
  326.     np->g_token = rp->g_token;
  327.     np->g_offs = rp->g_offs;
  328.     np->g_rno = rp->g_rno;
  329.     np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID);
  330. }
  331.  
  332. argmod(np)
  333. register NODEP np;
  334. {
  335.     int size = 0;
  336.  
  337.     if (np->g_token == ',') {
  338.         np->g_type = EV_RL;
  339.         size += argmod(np->n_right);
  340.         size += argmod(np->n_left);
  341.         return size;
  342.     }
  343.     size += onearg(np);
  344.     return size;
  345. }
  346.  
  347. onearg(np)
  348. register NODEP np;
  349. {
  350.     int rv;
  351.  
  352.     /* hack small ICON */
  353.     if (np->g_sz == 1 && np->g_token == ICON)
  354.         np->g_sz = 2;
  355.     /* hack push of 0 */
  356.     if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
  357.         addcode(np, "\tclr.S\t-(sp)\n");
  358.         return (int)np->g_sz;
  359.     }
  360.     /* hack push of #OREG */
  361.     if (np->g_token == OREG && isimmed(np)) {
  362.         np->g_flags &= ~IMMEDID;
  363.         addcode(np, "\tpea\tA\n");
  364.         return 4;
  365.     }
  366.  
  367.     if (np->g_ty == ET_A) {
  368.         rv = np->g_bsize;
  369.         strpush(np);
  370.         freetmps(np);
  371.         free1(NULL,np);
  372.         return rv;
  373.     }
  374.  
  375.     switch (np->g_sz) {
  376.     case 1:
  377.         addcode(np,
  378.            "\tmove.b\tA,d0\n\text.w\td0\n\tmove.w\td0,-(sp)\n");
  379.         return 2;
  380.     case 2:
  381.         addcode(np,
  382.            "\tmove.w\tA,-(sp)\n");
  383.         return 2;
  384.     default:
  385.         addcode(np,
  386.            "\tmove.l\tA,-(sp)\n");
  387.         return 4;
  388.     }
  389. }
  390.  
  391. #define MAXD DRV_START
  392. #define MAXA (ARV_START-AREG)
  393. #define NEEDALL (MAXA*AREG + MAXD)
  394.  
  395. order(np)
  396. register NODEP np;
  397. {
  398.     int l, r;
  399.  
  400.     switch (np->g_type) {
  401.     case E_BIN:
  402.         order(np->n_right);
  403.         r = np->n_right->g_needs;
  404.     case E_UNARY:
  405.         order(np->n_left);
  406.         l = np->n_left->g_needs;
  407.         break;
  408.     default:    /* leaf */
  409.         np->g_type = EV_NONE;
  410.         np->g_needs = 0;
  411.         return;
  412.     }
  413.  
  414.     if (np->g_type == E_UNARY) {
  415.         switch (np->g_token) {
  416.         case STAR:
  417.             np->g_needs = merge(l,AREG);
  418.             break;
  419.         case '(':
  420.             np->g_needs = NEEDALL;
  421.             break;
  422.         case POSTINC:
  423.         case POSTDEC:
  424.         case '!':
  425.             np->g_needs = merge(l,1);
  426.             break;
  427.         case '.':
  428.             if (np->g_fldw) {
  429.                 np->g_needs = merge(l,1);
  430.                 break;
  431.             }
  432.             /* else fall through */
  433.         default:
  434.             np->g_needs = l;
  435.         }
  436.         np->g_type = EV_LEFT;
  437.         return;
  438.     }
  439.  
  440. /* at this point, have binary node */
  441.  
  442.     switch (np->g_token) {
  443.     case DOUBLE '&':
  444.     case DOUBLE '|':
  445.     case '?':
  446.     case ':':
  447.         /* always left-right, no extra regs */
  448.         np->g_type = EV_LRSEP;
  449.         np->g_needs = merge(1, merge(l,r));
  450.         return;
  451.     case ',':
  452.         np->g_needs = merge(l, r);
  453.         np->g_type = EV_LRSEP;
  454.         return;
  455.     case '(':
  456.         np->g_needs = NEEDALL;
  457.         break;
  458.     case '^':
  459.     case DOUBLE '<':
  460.     case DOUBLE '>':
  461.     case ASSIGN '/':
  462.     case ASSIGN DOUBLE '<':
  463.     case ASSIGN DOUBLE '>':
  464.         np->g_needs = merge(bin(l,r), 2);
  465.         break;
  466.     default:
  467.         np->g_needs = merge(bin(l,r), 1);
  468.     }
  469.  
  470.     if (isassign(np->g_token) || np->g_token == '=')
  471.         np->g_type = EV_RL;    /* NO PUSHER's on L */
  472.     else
  473.         np->g_type = worst_1st(l, r);
  474.     flag_saves(np, l, r);
  475. }
  476.  
  477. flag_saves(np, l, r)
  478. NODEP np;
  479. {
  480.     NODEP *cpp;
  481.     register int other;
  482.  
  483.     if (np->g_type == EV_LR) {
  484.         cpp = &np->n_left;
  485.         other = r;
  486.     } else {
  487.         cpp = &np->n_right;
  488.         other = l;
  489.     }
  490.     if ((other & 7) >= MAXD || (other/AREG) >= MAXA)
  491.         addtmp(np, cpp);
  492. }
  493.  
  494. addtmp(np, cpp)
  495. NODEP np, *cpp;
  496. {
  497.     NODEP cp, tp;
  498.     NODEP copyone();
  499.  
  500.     cp = *cpp;
  501.     tp = copyone(cp);
  502.     tp->n_left = cp;
  503.     *cpp = tp;
  504.     tp->g_token = PUSHER;
  505.     strcpy(tp->n_name, "pusher");
  506.     tp->g_type = EV_LEFT;
  507. }
  508.  
  509. worst_1st(l,r)
  510. {
  511.     int ld, rd;
  512.  
  513.     ld = l & 7;
  514.     rd = r & 7;
  515.     if (rd > ld)
  516.         return EV_RL;
  517.     if (r > l)
  518.         return EV_RL;
  519.     return EV_LR;
  520. }
  521.  
  522. bin(l,r)
  523. {
  524.     int la, ra, na;
  525.     int ld, rd, nd;
  526.  
  527.     la = l/AREG;
  528.     ra = r/AREG;
  529.     ld = l & 7;
  530.     rd = r & 7;
  531.     na = la > ra ? la : ra;
  532.     if (ld == rd)
  533.         nd = ld == MAXD ? MAXD : ld+1;
  534.     else
  535.         nd = ld > rd ? ld : rd;
  536.     return na*AREG + nd;
  537. }
  538.  
  539. merge(need, have)
  540. {
  541.     int na, nd, ha, hd, xa, xd;
  542.  
  543.     na = need/AREG;
  544.     ha = have/AREG;
  545.     nd = need & 7;
  546.     hd = have & 7;
  547.     xa = na > ha ? na : ha;
  548.     xd = nd > hd ? nd : hd;
  549.     return xa*AREG + xd;
  550. }
  551.  
  552. holdlbls(np)
  553. NODEP np;
  554. {
  555.     np->g_bsize = new_lbl();
  556.     new_lbl();
  557. }
  558.  
  559. rinhlbls(np)
  560. NODEP np;
  561. {
  562.     np->g_bsize = np->n_right->g_bsize;
  563. }
  564.  
  565. /* limited version of same address check
  566.     assume one of these is a temp register */
  567. same_a(p1, p2)
  568. NODEP p1, p2;
  569. {
  570.     if (p1->g_token != p2->g_token)
  571.         return 0;
  572.     if (p1->g_rno != p2->g_rno)
  573.         return 0;
  574.     return 1;
  575. }
  576.  
  577. optadd(np, flags, sign)
  578. register NODEP np;
  579. {
  580.     NODEP lp = np->n_left, rp = np->n_right;
  581.  
  582.     if (rp->g_token != ICON)
  583.         return 0;
  584.     if (isimmed(lp) && isimmed(rp)) {
  585.         switch (lp->g_token) {
  586.         case OREG:
  587.         case ONAME:
  588.             inherit(np);
  589.             if (sign == -1)
  590.                 rp->g_offs = -rp->g_offs;
  591.             np->g_offs += rp->g_offs;
  592.  
  593.             if ((flags & IMMA_OK) == 0)
  594.                 imm_oreg(np);
  595.             return 1;
  596.         default:
  597.             return 0;
  598.         }
  599.     }
  600.     return 0;
  601. }
  602.  
  603. iscc(np)
  604. NODEP np;
  605. {
  606.     return (np->g_token >= BR_TOK) || (np->g_flags & SIDE_CC);
  607. }
  608.  
  609. cc_hack(np)
  610. NODEP np;
  611. {
  612.     if (isareg(np))
  613.         return;
  614.     np->g_flags |= SIDE_CC;
  615. }
  616.  
  617. cctok(np)
  618. NODEP np;
  619. {
  620.     if (np->g_token >= BR_TOK)
  621.         return np->g_token - BR_TOK;
  622.     if (np->g_flags & SIDE_CC)
  623.         return B_NE;
  624.     printf("cctok error ");
  625.     return 0;
  626. }
  627.